package com.zis.platform.common.log;

import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zis.platform.common.authentication.UserToken;
import com.zis.platform.core.entity.LogOpterationEntity;
import com.zis.platform.core.entity.UserEntity;
import com.zis.util.RemoteUtil;

/**
 * 
 * <b>说明：</b>操作日志拦截切面
 * 
 * @ClassName: OperationLogAspect
 * @author zhaohaitao(2543)
 * @date 2015-7-10 上午10:12:57
 * 
 */
public class OperationLogAspect
{
    
    Logger logger = Logger.getLogger(OperationLogAspect.class);
    
    /**
     * 异常通知:
     * 
     * @param joinPoint
     * @param e
     */
    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
    {
        parseInfo2Log(joinPoint, e);
    }
    
    /**
     * 后置通知 ： 在方法抛出异常退出时执行的通知。
     * 
     * @param jp 连接点：程序执行过程中的某一行为，例如，AServiceImpl.barA()的调用或者抛出的异常行为
     */
    public void doAfter(JoinPoint joinPoint)
    {
        parseInfo2Log(joinPoint);
    }
    
    private void parseInfo2Log(JoinPoint joinPoint)
    {
        parseInfo2Log(joinPoint, null);
    }
    
    private void parseInfo2Log(JoinPoint joinPoint, Exception expection)
    {
        ServletRequestAttributes attrs = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if (attrs != null)
        {
            StringBuffer pathInfo = attrs.getRequest().getRequestURL();
            if (pathInfo != null && !pathInfo.toString().endsWith(".jhtml"))
            {
                Subject subject = SecurityUtils.getSubject();
                UserToken token = (UserToken)subject.getPrincipal();
                HttpServletRequest request = attrs.getRequest();
                LogOpterationEntity log = new LogOpterationEntity();
                log.setLogId(UUID.randomUUID().toString());
                log.setIp(request.getRemoteAddr());
                log.setOptDate(new Date());
                log.setMac(RemoteUtil.getMACAddress(request));
                if (token != null)
                {
                    UserEntity user = token.getUser();
                    log.setOptUser(user.getLoginName());
                    log.setOptUserId(user.getUserId());
                }
                log.setUrl(request.getRequestURI());
                Enumeration<String> parameterNames = request.getParameterNames();
                StringBuffer logStr = new StringBuffer();
                while (parameterNames.hasMoreElements())
                {
                    String nextElement = parameterNames.nextElement();
                    String[] parameterValues = request.getParameterValues(nextElement);
                    logStr.append(nextElement + "=" + Arrays.toString(parameterValues)).append(";");
                }
                log.setParameters(logStr.toString());
                log.setServiceClassName(joinPoint.getTarget().getClass().getName() + " : "
                    + joinPoint.getSignature().getName());
                Object[] params = joinPoint.getArgs();
                if (params != null && params.length > 0)
                {
                    StringBuffer sb = new StringBuffer();
                    for (Object obj : params)
                    {
                        sb.append("{").append(toString(obj)).append("}");
                        
                    }
                    log.setMethodParameters(sb.toString());
                }
                if (expection != null)
                {
                    Object[] array =
                        {joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(),
                            expection.getClass().getName(), expection.getMessage(), params};
                    String exceptionStr = String.format("异常方法:%s  异常代码:%s   异常信息:%s  参数:%s ", array);
                    log.setException(exceptionStr);
                }
                ObjectMapper mapper = new ObjectMapper();
                try
                {
                    String logString = mapper.writeValueAsString(log);
                    logger.warn(logString);
                }
                catch (JsonProcessingException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 将请求参数值转换为字符串
     * 
     * @param object
     * @return
     */
    private String toString(Object object)
    {
        if (object == null)
        {
            return "<null>";
        }
        else if (object instanceof String[])
        {
            String[] params = (String[])object;
            return Arrays.toString(params);
        }
        else if (object instanceof List)
        {
            StringBuffer sb = new StringBuffer("items{");
            for (Object obj : (List)object)
            {
                sb.append(obj.toString());
            }
            sb.append("}");
            return sb.toString();
        }
        else
        {
            return object.toString();
        }
        
    }
}